<?php

namespace app\common\service\word;

use app\common\enums\ResourcesTypeEnum;
use app\common\enums\WordStatusEnum;
use app\common\model\banxi\core\CoreVocabularyLexicon;
use app\common\model\banxi\course\Lexicon;
use app\common\model\banxi\word\WordDictionary;
use app\common\model\banxi\word\WordResources;
use app\common\service\ApiService;
use app\common\service\DouBaoAiWordService;
use app\common\service\TTLService;
use ba\Exception;
use think\db\exception\PDOException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\facade\Db;

class WordService extends ApiService
{

    /**
     * 创建队列任务
     * @return array|bool
     */
    public function wordCompositing()
    {
        try {
            WordDictionary::where([
                'status' => WordStatusEnum::E1
            ])->field('id,word')->chunk(5, function ($list) {
                $words = $list->toArray();
                foreach ($words as $item) {
                    logSave([
                        'file' => __FILE__,
                        'message' => 'Word Split Exec',
                        'word_id' => $item['id'],
                        'word' => $item['word'],
                        'start_time' => date('Y-m-d H:i:s')
                    ], 'wordCompositing');
                    try {
                        $result = $this->wordSplit($item);
                        if ($result) {
                            $message = '成功';
                        } else {
                            $message = $this->getError();
                        }
                        logSave([
                            'file' => __FILE__,
                            'message' => 'Word Split Finished',
                            'word_id' => $item['id'],
                            'word' => $item['word'],
                            'end_time' => date('Y-m-d H:i:s'),
                            'result' => $result ? 'success' : 'failed',
                            'resultMsg' => $message
                        ], 'wordCompositing');
                    } catch (\Exception $e) {
                        logSave([
                            'file' => __FILE__,
                            'message' => 'Word Split Exception',
                            'word_id' => $item['id'],
                            'word' => $item['word'],
                            'error' => $e->getMessage(),
                            'fileInfo' => $e->getFile(),
                            'line' => $e->getLine()
                        ], 'wordCompositing');
                    }
                }
                return true;
            });
        } catch (\Exception $e) {
            logSave([
                'file' => __FILE__,
                'message' => 'WordRunner Error',
                'error' => $e->getMessage(),
                'fileInfo' => $e->getFile(),
                'line' => $e->getLine()
            ], 'wordCompositing');
            $this->setError($e->getMessage());
            return false;
        }
        return true;
    }

    public function wordSplit($wordDictionary)
    {
        Db::startTrans();
        try {
            $word = $wordDictionary['word'];
            $wordId = $wordDictionary['id'];

            // 获取单词信息
            $douBaoAiWordService = new DouBaoAiWordService();
            $wordResp = $douBaoAiWordService->getWord($word);

            // 清理数据
            $spells = $wordResp['spells'] ?? [];
            if (!empty($spells)) {
                foreach ($spells as &$spell) {
                    if (isset($spell['item'])) {
                        $spell['item'] = preg_replace('/[^a-zA-Z]/', '', $spell['item']);
                    }
                }
                unset($spell);
            }

            $syllables = $wordResp['syllables'] ?? [];
            if (!empty($syllables)) {
                foreach ($syllables as &$syllable) {
                    if (isset($syllable['item'])) {
                        $syllable['item'] = preg_replace('/[^a-zA-Z]/', '', $syllable['item']);
                    }
                }
                unset($syllable);
            }

            // 验证数据完整性
            if (empty($wordResp['zh']) || empty($wordResp['phonetic'])) {
                throw new ValidateException('返回数据不完整');
            }

            $wordUtilsService = new WordUtilsService();

            // 构建更新数据
            $updateEntity = [
                'translation' => $wordResp['zh'],
                'phonetic' => $wordResp['phonetic'],
                'phoneticSplit' => json_encode($wordUtilsService->phoneticSplit($wordResp['phonetic']), JSON_UNESCAPED_UNICODE),
                'metaConsonant' => json_encode($spells, JSON_UNESCAPED_UNICODE),
                'metaVowel' => json_encode($syllables, JSON_UNESCAPED_UNICODE),
                'exampleSentence' => json_encode($wordResp['examples'] ?? []),
                'status' => WordStatusEnum::E2
            ];

            // 验证单词一致性
            $wordValid = preg_replace('/[^a-zA-Z]/', '', $word);

            // 验证 syllables 数据一致性
            $syllableStr = '';
            foreach ($syllables as $syllable) {
                $syllableStr .= $syllable['item'] ?? '';
            }
            if ($wordValid != $syllableStr) {
                $updateEntity['status'] = WordStatusEnum::E3;
                logSave([
                    'file' => __FILE__,
                    'message' => 'Syllables数据不一致',
                    'word' => $word,
                    'expected' => $wordValid,
                    'actual' => $syllableStr
                ], 'wordSplit');
            }

            // 验证 spells 数据一致性
            $spellStr = '';
            foreach ($spells as $spell) {
                $spellStr .= $spell['item'] ?? '';
            }
            if ($wordValid != $spellStr) {
                $updateEntity['status'] = WordStatusEnum::E3;
                logSave([
                    'file' => __FILE__,
                    'message' => 'Spells数据不一致',
                    'word' => $word,
                    'expected' => $wordValid,
                    'actual' => $syllableStr
                ], 'wordSplit');
            }

            // 处理资源数据
            try {
                $wordResources = new WordResources();
                $examples = $wordResp['examples'] ?? [];

                if (!empty($examples)) {
                    $examplesUpdate = array_map(function ($example) {
                        return $example['en'];
                    }, $examples);
                    if (!empty($examplesUpdate)) {
                        $wordResources->updateFill($examplesUpdate, ResourcesTypeEnum::E4);
                    }
                }

                if (!empty($syllables)) {
                    $syllablesUpdate = array_map(function ($syllable) {
                        return $syllable['pronounce'] ?? '';
                    }, $syllables);
                    if (!empty($syllablesUpdate)) {
                        $wordResources->updateFill($syllablesUpdate, ResourcesTypeEnum::E3);
                    }
                }

                if (!empty($spells)) {
                    $spellsUpdate = array_map(function ($spell) {
                        return $spell['pronounce'] ?? '';
                    }, $spells);
                    if (!empty($spellsUpdate)) {
                        $wordResources->updateFill($spellsUpdate, ResourcesTypeEnum::E3);
                    }
                }
            } catch (PDOException|ValidateException $e) {
                logSave([
                    'file' => __FILE__,
                    'message' => 'wordSplit error',
                    'error' => $e->getMessage()
                ], 'wordSplit');
                $updateEntity['status'] = WordStatusEnum::E3;
            }

            // 更新单词字典
            $wordDictionaryModel = new WordDictionary();
            $wordDictionaryModel->update($updateEntity, ['id' => $wordId]);

            // 更新词汇表
            $lexiconModel = new Lexicon();
            $lexiconModel->updateTranslationByWord($word, $updateEntity['translation'], $updateEntity['phonetic']);

            Db::commit();
            return true;
        } catch (PDOException|ValidateException|HttpResponseException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        } catch (\Exception $e) {
            Db::rollback();
            logSave([
                'file' => __FILE__,
                'message' => 'Word Split Exception',
                'word_id' => $wordDictionary['id'] ?? null,
                'word' => $wordDictionary['word'] ?? null,
                'error' => $e->getMessage(),
                'fileInfo' => $e->getFile(),
                'line' => $e->getLine()
            ], 'wordSplit');
            $this->setError($e->getMessage());
            return false;
        }
    }

    public function vocalSynthesis()
    {
        $coreVocabularyLexiconModel = new CoreVocabularyLexicon();
        $wordResourcesModel = new WordResources();
        try {
            // 执行各类音频合成任务
            $result = 0;
            $result += $this->audioCompositing();
            $result += $coreVocabularyLexiconModel->audioCompositing();
            $result += $wordResourcesModel->audioCompositing();
            return ['result' => $result];
        } catch (Exception|PDOException|ValidateException $e) {
            logSave([
                'file' => __FILE__,
                'message' => 'vocalSynthesis error',
                'error' => $e->getMessage(),
                'fileInfo' => $e->getFile(),
                'line' => $e->getLine()
            ], 'vocalSynthesis');
            $this->setError($e->getMessage());
            return false;
        }
    }

    /**
     * 音频合成 - 处理单词发音
     * @return int 处理的记录数
     */
    public function audioCompositing()
    {
        $count = WordDictionary::where(['isSynthesis' => 0])
            ->count();
        $chunkSize = 50;
        $totalPage = ceil($count / $chunkSize);
        try {
            for ($page = 1; $page <= $totalPage; $page++) {
                $words = WordDictionary::where(['isSynthesis' => 0])
                    ->field('id,word')
                    ->page($page, $chunkSize)
                    ->select();
                foreach ($words as $item) {
                    try {
                        $res = $this->wordVocal($item['word']);
                        if ($res) {
                            $count++;
                        } else {
                            logSave([
                                'file' => __FILE__,
                                'message' => 'Word vocal synthesis failed',
                                'word' => $item['word'],
                                'error' => $this->getError()
                            ], 'audioCompositing');
                        }
                    } catch (\Exception $e) {
                        logSave([
                            'file' => __FILE__,
                            'message' => 'Single word vocal synthesis failed',
                            'word' => $item['word'],
                            'error' => $e->getMessage()
                        ], 'audioCompositing');
                    }
                }
            }
        } catch (\Exception $e) {
            logSave([
                'file' => __FILE__,
                'message' => 'audioCompositing error',
                'word' => $item['word'],
                'error' => $e->getMessage(),
                'fileInfo' => $e->getFile(),
                'line' => $e->getLine()
            ], 'audioCompositing');
        }
        return $count;
    }

    public function wordVocal(string $text)
    {
        logSave([
            'file' => __FILE__,
            'message' => 'Word vocal synthesis Exec',
            'word' => $text,
            'start_time' => date('Y-m-d H:i:s')
        ], 'wordVocal');
        try {
            // 验证单词是否已存在音频
            $wordDictionary = WordDictionary::where(['word' => $text])->find();
            if (!$wordDictionary) {
                $this->setError('单词不存在');
                return false;
            }

            // 如果已经有音频，跳过处理
            if ($wordDictionary['isSynthesis'] == 1 && !empty($wordDictionary['wordAudio'])) {
                return true;
            }

            $TTLService = new TTLService();
            $res = $TTLService->getEnVocalToUrl($text);
            if (!$res) {
                throw new ValidateException($TTLService->getError());
            }
            $url = $res;
            $wordDictionaryModel = new WordDictionary();
            $wordDictionaryModel->update([
                'wordAudio' => $url,
                'isSynthesis' => 1
            ], ['word' => $text]);

            $lexiconModel = new Lexicon();
            $lexiconModel->updateAudioByWord($text, $url);
            logSave([
                'file' => __FILE__,
                'message' => 'Word vocal synthesis Finished',
                'word' => $text,
                'end_time' => date('Y-m-d H:i:s')
            ], 'wordVocal');
            return true;
        } catch (Exception|PDOException|ValidateException $e) {
            logSave([
                'file' => __FILE__,
                'message' => 'Word vocal synthesis error',
                'word' => $text,
                'error' => $e->getMessage()
            ], 'wordVocal');
            $this->setError($e->getMessage());
            return false;
        } catch (\Exception $e) {
            logSave([
                'file' => __FILE__,
                'message' => 'Word vocal synthesis Exception',
                'error' => $e->getMessage(),
                'fileInfo' => $e->getFile(),
                'line' => $e->getLine()
            ], 'wordVocal');
            $this->setError('系统错误');
            return false;
        }
    }

    //核心单词-拆分
    public function sayWordCompositing($wordList)
    {
        if (empty($wordList)) {
            return true;
        }
        foreach ($wordList as $item) {
            if (empty($item['wordEn'])) {
                continue;
            }
            logSave([
                'file' => __FILE__,
                'message' => 'say Word Split Exec',
                'wordInfo' => $item,
                'start_time' => date('Y-m-d H:i:s')
            ], 'sayWordCompositing');
            try {
                $phonetic = $item['phonetic'] ?? '';
                $audio = $item['audio'] ?? '';
                $word = trim($item['wordEn']);
                $result = $this->sayWordSplit($word, $phonetic, $audio);
                if ($result) {
                    $message = '成功';
                } else {
                    $message = $this->getError();
                }
                logSave([
                    'file' => __FILE__,
                    'message' => 'Say Word Split Finished',
                    'wordInfo' => $item,
                    'end_time' => date('Y-m-d H:i:s'),
                    'result' => $result ? 'success' : 'failed',
                    'resultMsg' => $message
                ], 'sayWordCompositing');
            } catch (\Exception $e) {
                logSave([
                    'file' => __FILE__,
                    'message' => 'Say Word Split Exception',
                    'wordInfo' => $item,
                    'error' => $e->getMessage(),
                    'fileInfo' => $e->getFile(),
                    'line' => $e->getLine()
                ], 'sayWordCompositing');
            }

        }
        return true;
    }

    public function sayWordSplit($word, $phonetic, $audio)
    {
        Db::startTrans();
        try {
            $wordId = 0;
            $wordDictionaryModel = new WordDictionary();
            $wordDictionary = $wordDictionaryModel->where(['word' => $word])->find();
            if ($wordDictionary) {
                if ($wordDictionary['status'] == WordStatusEnum::E2) {
                    return true;
                }
                $wordId = $wordDictionary['id'];
            }
            // 获取单词信息
            $douBaoAiWordService = new DouBaoAiWordService();
            $wordResp = $douBaoAiWordService->getWord($word);

            // 清理数据
            $spells = $wordResp['spells'] ?? [];
            if (!empty($spells)) {
                foreach ($spells as &$spell) {
                    if (isset($spell['item'])) {
                        $spell['item'] = preg_replace('/[^a-zA-Z]/', '', $spell['item']);
                    }
                }
                unset($spell);
            }

            $syllables = $wordResp['syllables'] ?? [];
            if (!empty($syllables)) {
                foreach ($syllables as &$syllable) {
                    if (isset($syllable['item'])) {
                        $syllable['item'] = preg_replace('/[^a-zA-Z]/', '', $syllable['item']);
                    }
                }
                unset($syllable);
            }

            // 验证数据完整性
            if (empty($wordResp['zh']) || empty($wordResp['phonetic'])) {
                throw new ValidateException('返回数据不完整');
            }

            $wordUtilsService = new WordUtilsService();

            // 构建更新数据
            $updateEntity = [
                'translation' => $wordResp['zh'],
                'phonetic' => $phonetic ?? $wordResp['phonetic'],
                'wordAudio' => $audio,
                'phoneticSplit' => json_encode($wordUtilsService->phoneticSplit($wordResp['phonetic']), JSON_UNESCAPED_UNICODE),
                'metaConsonant' => json_encode($spells, JSON_UNESCAPED_UNICODE),
                'metaVowel' => json_encode($syllables, JSON_UNESCAPED_UNICODE),
                'exampleSentence' => json_encode($wordResp['examples'] ?? []),
                'isSynthesis' => 1,
                'status' => WordStatusEnum::E2
            ];
            if (empty($audio)) {
                $updateEntity['isSynthesis'] = 0;
            }
            // 验证单词一致性
            $wordValid = preg_replace('/[^a-zA-Z]/', '', $word);

            // 验证 syllables 数据一致性
            $syllableStr = '';
            foreach ($syllables as $syllable) {
                $syllableStr .= $syllable['item'] ?? '';
            }
            if ($wordValid != $syllableStr) {
                $updateEntity['status'] = WordStatusEnum::E3;
                logSave([
                    'file' => __FILE__,
                    'message' => 'Syllables数据不一致',
                    'word' => $word,
                    'expected' => $wordValid,
                    'actual' => $syllableStr
                ], 'sayWordSplit');
            }

            // 验证 spells 数据一致性
            $spellStr = '';
            foreach ($spells as $spell) {
                $spellStr .= $spell['item'] ?? '';
            }
            if ($wordValid != $spellStr) {
                $updateEntity['status'] = WordStatusEnum::E3;
                logSave([
                    'file' => __FILE__,
                    'message' => 'Spells数据不一致',
                    'word' => $word,
                    'expected' => $wordValid,
                    'actual' => $syllableStr
                ], 'sayWordSplit');
            }

            // 处理资源数据
            try {
                $wordResources = new WordResources();
                $examples = $wordResp['examples'] ?? [];

                if (!empty($examples)) {
                    $examplesUpdate = array_map(function ($example) {
                        return $example['en'];
                    }, $examples);
                    if (!empty($examplesUpdate)) {
                        $wordResources->updateFill($examplesUpdate, ResourcesTypeEnum::E4);
                    }
                }

                if (!empty($syllables)) {
                    $syllablesUpdate = array_map(function ($syllable) {
                        return $syllable['pronounce'] ?? '';
                    }, $syllables);
                    if (!empty($syllablesUpdate)) {
                        $wordResources->updateFill($syllablesUpdate, ResourcesTypeEnum::E3);
                    }
                }

                if (!empty($spells)) {
                    $spellsUpdate = array_map(function ($spell) {
                        return $spell['pronounce'] ?? '';
                    }, $spells);
                    if (!empty($spellsUpdate)) {
                        $wordResources->updateFill($spellsUpdate, ResourcesTypeEnum::E3);
                    }
                }
            } catch (PDOException|ValidateException $e) {
                logSave([
                    'file' => __FILE__,
                    'message' => 'sayWordSplit error',
                    'error' => $e->getMessage()
                ], 'sayWordSplit');
                $updateEntity['status'] = WordStatusEnum::E3;
            }

            if ($wordId) {
                // 更新单词字典
                $wordDictionaryModel->update($updateEntity, ['id' => $wordId]);
            } else {
                $updateEntity['word'] = $word;
                $firstLetter = WordUtilsService::getFirstLetter($word);
                $updateEntity['firstLetter'] = $firstLetter;
                $wordDictionaryModel->save($updateEntity);
            }
            Db::commit();
            return true;
        } catch (PDOException|ValidateException|HttpResponseException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        } catch (\Exception $e) {
            Db::rollback();
            logSave([
                'file' => __FILE__,
                'message' => 'Say Word Split Exception',
                'word_id' => $wordDictionary['id'] ?? null,
                'word' => $wordDictionary['word'] ?? null,
                'error' => $e->getMessage(),
                'fileInfo' => $e->getFile(),
                'line' => $e->getLine()
            ], 'sayWordSplit');
            $this->setError($e->getMessage());
            return false;
        }
    }

    public function sayVocalSynthesis()
    {
        $wordResourcesModel = new WordResources();
        try {
            // 执行各类音频合成任务
            $result = 0;
            $result += $this->audioCompositing();
            $result += $wordResourcesModel->audioCompositing();
            return ['result' => $result];
        } catch (Exception|PDOException|ValidateException $e) {
            logSave([
                'file' => __FILE__,
                'message' => 'vocalSynthesis error',
                'error' => $e->getMessage(),
                'fileInfo' => $e->getFile(),
                'line' => $e->getLine()
            ], 'vocalSynthesis');
            $this->setError($e->getMessage());
            return false;
        }
    }
}
